# -*- coding: utf-8 -*-
#
# Copyright (c) 2010-2011, Monash e-Research Centre
#   (Monash University, Australia)
# Copyright (c) 2010-2011, VeRSI Consortium
#   (Victorian eResearch Strategic Initiative, Australia)
# Copyright (c) 2011,2012 RMIT e-Research Office
#   (RMIT University, Australia)
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#    *  Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#    *  Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#    *  Neither the name of RMIT University, Monash University, 
#       the VeRSI, the VeRSI Consortium members, nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

"""
.. module:: ANDSService
   :synopsis: Publishes Collections to ANDS

.. moduleauthor:: Ian Thomas <Ian.Edward.Thomas@rmit.edu.au>

"""

import logging
from django.conf import settings
from django.utils.importlib import import_module
from django.core.exceptions import ImproperlyConfigured
from smra.smra_portal.models import VirtualCollection


logger = logging.getLogger(__name__)

class ANDSService():
    
    def __init__(self, virt, settings=settings):
        self._publish_providers = []
        self._initialised = False
        self.settings = settings
        self.virt = virt

    def _manual_init(self):
        """Manual init had to be called by all the functions of the PublishService
        class to initialise the instance variables. This block of code used to
        be in the __init__ function but has been moved to its own init function
        to get around the problems with cyclic imports to static variables
        being exported from auth related modules.

        """
        for pp in self.settings.PUBLISH_PROVIDERS:
            self._publish_providers.append(self._safe_import(pp))
        self._initialised = True

    def _safe_import(self, path):
        try:
            dot = path.rindex('.')
        except ValueError:
            raise ImproperlyConfigured(\
                '%s isn\'t a middleware module' % path)
        publish_module, publish_classname = path[:dot], path[dot + 1:]
        try:
            mod = import_module(publish_module)
        except ImportError, e:
            raise ImproperlyConfigured(\
                'Error importing publish module %s: "%s"' %
                                       (publish_module, e))
        try:
            publish_class = getattr(mod, publish_classname)
        except AttributeError:
            raise ImproperlyConfigured(\
                'Publish module "%s" does not define a "%s" class' %
                                       (publish_module, publish_classname))

        publish_instance = publish_class(self.virt)
        return publish_instance

    def get_publishers(self):
        """Return a list publish providers

        """
        if not self._initialised:
            self._manual_init()

        publicaton_list = [pp for pp in self._publish_providers]
        return publicaton_list

    def get_template_paths(self):
        """Returns a list of relative file paths to html templates

        """
        if not self._initialised:
            self._manual_init()
        path_list = []
        for pp in self._publish_providers:
            logger.debug("mygroup provider: %s %s" % (pp.name,pp.get_path()))
            path_list.append(pp.get_path())
        return path_list

    def get_contexts(self, request):
        """Gets context dictionaries for each PublishProvider

        :param request: a HTTP Request instance
        :type request: :class:`django.http.HttpRequest`
        """
        if not self._initialised:
            self._manual_init()
        contexts = {}
        for pp in self._publish_providers:
            # logger.debug("group provider: " + gp.name)
            context = pp.get_context(request)
            if context:
                contexts = dict(contexts, **context)
        return contexts

    def execute_publishers(self, request):
        """Executes each publish provider in a chain.
        If any publish provider fails then the experiment is not made public

        :param request: a HTTP Request instance
        :type request: :class:`django.http.HttpRequest`
        """
        if not self._initialised:
            self._manual_init()

        pp_status_list = []
        for pp in self._publish_providers:
            logger.debug("pp=%s" % pp)
            
            try:
                pp_response = pp.execute_publish(request)
            except Exception as inst:
                
                logger.debug("exception %s" % inst)
                logger.debug("virt=%s" % self.virt)
                #virt = VirtualCollection.objects.get(pk=self.virt.id)
                self.virt.public = False
                self.virt.save()
                
                logger.error('Publish Provider Exception: ' +
                pp.name + ' on virt: ' + str(self.virt.pk) +
                ' failed with message "' +
                str(inst) + '""')

                pp_response = {'status': False, 'message': str(inst)}

            if pp_response['status']:
                logger.info('Publish Provider: ' +
                pp.name + ' executed on virt: ' +
                str(self.virt.pk) + ' with success: ' +
                str(pp_response['status']) + ' and message: ' +
                pp_response['message'])
            else:
                logger.error('Publish Provider: ' +
                pp.name + ' executed on virt: ' +
                str(self.virt.pk) + ' FAILED with message: ' +
                pp_response['message'])

            pp_status_list.append({'name': pp.name,
            'status': pp_response['status'],
            'message': pp_response['message']})
        return pp_status_list
